package com.gitee.feizns.quickstart.dict.spring.boot.autoconfigure.db.mybatis.flex.pojo;

import com.fasterxml.jackson.databind.JsonNode;
import com.gitee.feizns.dynamic.Lists;
import com.gitee.feizns.quickstart.ddl.annotation.Comment;
import com.gitee.feizns.quickstart.dict.Entry;
import com.gitee.feizns.quickstart.dict.Permission;
import com.gitee.feizns.quickstart.jackson.Val;
import com.gitee.feizns.quickstart.mybatis.flex.jpa.AutoIdPojo;
import com.mybatisflex.core.handler.JacksonTypeHandler;
import com.mybatisflex.core.query.QueryChain;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.annotations.Type;

import javax.persistence.Column;
import javax.persistence.Entity;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * qk字典
 * @author feizns
 * @since 2024/12/20
 */
@Entity
@Getter
@Setter
@Comment("qk字典")
@ToString(callSuper = true)
public class QkDict extends AutoIdPojo<QkDict> implements Entry {

    /**
     * 字典键
     */
    @Comment("字典键（唯一）")
    @Column(name = "`key`", unique = true)
    @com.mybatisflex.annotation.Column(value = "key", onUpdateValue = "`key`")
    private String key;

    /**
     * 字典值
     */
    @Type(type = "json")
    @Comment("字典值")
    @Column(columnDefinition = "JSON")
    @com.mybatisflex.annotation.Column(typeHandler = JacksonTypeHandler.class)
    private JsonNode value;

    /**
     * 许可
     */
    @Comment("访问许可（Readonly=只读、ReadWrite=读写）")
    @Column(columnDefinition = "VARCHAR(255)")
    private Permission permission;

    /**
     * 备注描述
     */
    @Comment("备注描述")
    private String description;

    /**
     * qk
     * @param e e
     * @return {@link QkDict}
     */
    public static QkDict ofEntry(Entry e) {
        return new QkDict().of(e);
    }

    /**
     * 根据key查找字典
     * @param key 钥匙
     * @return {@link QkDict }
     */
    public static QkDict find(String key) {
        return QueryChain.of(QkDict.class).eq(QkDict::getKey, key).one();
    }

    /**
     * 根据key查找字典
     * @param keys 钥匙
     * @return {@link QkDict }
     */
    public static Map<String, QkDict> find(String... keys) {
        return find(Lists.of(keys));
    }

    /**
     * 根据key查找字典
     * @param keys 钥匙
     * @return {@link Map }<{@link String }, {@link QkDict }>
     */
    public static Map<String, QkDict> find(List<String> keys) {
        Map<String, QkDict> result = new LinkedHashMap<>();
        for (String key : keys)
            result.put(key, find(key));
        return result;
    }

    /**
     * 存储字典
     * @param entry {@link Entry}
     * @return {@link QkDict }
     */
    public static QkDict put(Entry entry) {
        QkDict dict = findAsOpt(entry.getKey()).orElse(new QkDict().of(entry));
        dict.saveOrUpdate();
        return dict;
    }

    /**
     * 根据key查找字典
     * @param key 钥匙
     * @return {@link QkDict }
     */
    public static Optional<QkDict> findAsOpt(String key) {
        return QueryChain.of(QkDict.class).eq(QkDict::getKey, key).oneOpt();
    }

    /**
     * qk
     * @param e e
     * @return {@link QkDict}
     */
    public QkDict of(Entry e) {
        setKey(e.getKey());
        setValue(Val.of(e.getValue()).jsonNode());
        setPermission(e.getPermission());
        return this;
    }

    /**
     * 之
     * @param key 钥匙
     * @param value 值
     * @return {@link QkDict }
     */
    public static QkDict of(String key, Object value) {
        return of(key, value, Permission.ReadWrite);
    }

    /**
     * 之
     * @param key 钥匙
     * @param value 值
     * @param permission 许可
     * @return {@link QkDict }
     */
    public static QkDict of(String key, Object value, Permission permission) {
        return of(key, value, permission, null);
    }

    /**
     * 之
     * @param key 钥匙
     * @param value 值
     * @param permission 许可
     * @return {@link QkDict }
     */
    public static QkDict of(String key, Object value, Permission permission, String description) {
        QkDict entry = new QkDict();
        entry.setKey(key);
        entry.setValue(Val.of(value).jsonNode());
        entry.setPermission(permission);
        entry.setDescription(description);
        return entry;
    }

}
